module ysyx_050369_alu(
    input               clk,
    input               rst,
    input [63:0]        op1,
    input [63:0]        op2,
    input [5:0]         ALUctr,
    input               stop,
    output reg [63:0]   res,
    output              ALU_busy 
);
//ALUctr    
// `define 050369_alu_add      3'b000   alu_ctr[3]=0 add; =1 sub
// `define 050369_alu_sll      3'b001
// `define 050369_alu_less     3'b010//alu_ctr[3]=0 unsigned less; =1 signed less
// `define 050369_alu_setB     3'b011
// `define 050369_alu_xor      3'b100
// `define 050369_alu_srl      3'b101  alu_ctr[3]=0 逻辑右移; =1 算数右移
// `define 050369_alu_or       3'b110
// `define 050369_alu_and      3'b111
wire [63:0]add_res;

wire CF,OF,SF;
ysyx_050369_add add(
    .add_op1(op1),
    .add_op2(op2),
    .sub_flag(ALUctr[4]),
    .result(add_res),
    .CF(CF),
    .SF(SF),
    .OF(OF)
);

wire [63: 0]res_sll;
wire [63: 0]res_xor;
wire [63: 0]res_or;
wire [63: 0]res_and;
wire [63: 0]res_srl;
wire [63: 0]res_sra;
wire [31: 0]res_srlw;
wire [31: 0]res_sraw;
assign res_sll  = op1 << op2[5:0];
assign res_xor  = op1 ^ op2;
assign res_or   = op1 | op2;
assign res_and  = op1 & op2;
assign  res_srl  = {64'b0,op1}[({1'b0,op2[5:0]})+:64];
// assign res_srl  = op1 >>op2[5:0];
assign  res_sra  = {{64{op1[63]}},op1}[({1'b0,op2[5:0]})+:64];
// assign res_sra  ={{64{op1[63]}},op1}>>op2[5:0];
assign  res_srlw  = {32'b0,op1[31:0]}[({1'b0,op2[4:0]})+:32];
// assign res_srlw = op1[31:0]>>op2[4:0];
assign  res_sraw  = {{32{op1[31]}},op1[31:0]}[({1'b0,op2[4:0]})+:32];
// assign res_sraw = {{96{op1[31]}},op1[31:0]}>>op2[4:0];


wire mul_valid;
wire [1:0] mul_signed;
wire mul_ready;
wire mul_out_valid;
wire [63:0]result_hi,result_lo;
wire div_valid;
wire div_out_valid;
wire div_ready;
wire [63:0] quotient,remainder;

assign mul_valid = (ALUctr[3] && ~ALUctr[2])&mul_ready&stop;
assign div_valid = (ALUctr[3] &&  ALUctr[2])&div_ready&stop;
assign ALU_busy =(~(mul_ready||mul_out_valid)||mul_valid)||(~(div_ready||div_out_valid)||div_valid);
assign mul_signed[0] = ~ALUctr[1] &&  ALUctr[0];
assign mul_signed[1] = ALUctr[1] ^ ALUctr[0];
// MuxKeyWithDefault #(4, 2, 2) i3 (mul_signed, ALUctr[1:0], 2'b0, {
//     2'b00,2'b00,
//     2'b01,2'b11,
//     2'b10,2'b10,
//     2'b11,2'b00
// });
`ifdef ysyx_050369_BOOTH
ysyx_050369_Bmultiplier Bmultiplier (
    .clk         (clk),   
    .rst         (rst),
    .mul_valid   (mul_valid),
    .flush       ('b0),//	为高表示取消乘法
    .mulw        (ALUctr[5]),//为高表示是 32 位乘法
    .mul_signed  (mul_signed),//2’b11（signed x signed）；2’b10（signed x unsigned）；2’b00（unsigned x unsigned）；
    .multiplicand(op1),
    .multiplier  (op2),
    .mul_ready   (mul_ready),
    .out_valid   (mul_out_valid),
    .result_hi   (result_hi),
    .result_lo   (result_lo)
);
`else
ysyx_050369_Smultiplier Smultiplier (
    .clk         (clk),   
    .rst         (rst),
    .mul_valid   (mul_valid),
    .flush       ('b0),//	为高表示取消乘法
    .mulw        (ALUctr[5]),//为高表示是 32 位乘法
    .mul_signed  (mul_signed),//2’b11（signed x signed）；2’b10（signed x unsigned）；2’b00（unsigned x unsigned）；
    .multiplicand(op1),
    .multiplier  (op2),
    .mul_ready   (mul_ready),
    .out_valid   (mul_out_valid),
    .result_hi   (result_hi),
    .result_lo   (result_lo)
);
`endif

ysyx_050369_DIV  DIV( 
    .clk         (clk),
    .rst         (rst),
    .dividend    (op1),
    .divisor     (op2),
    .div_valid   (div_valid),
    .divw        (ALUctr[5]),
    .div_signed  (ALUctr[4]),
    .flush       ('b0),
    .div_ready   (div_ready),
    .out_valid   (div_out_valid),
    .quotient    (quotient),//商
    .remainder   (remainder)//	余数
);
    always @(*) begin
        case (ALUctr[3:0])
            `ysyx_050369_alu_add    :res = ALUctr[5]?{{32{add_res[31]}},add_res[31:0]}:add_res;
            `ysyx_050369_alu_sll    :res = ALUctr[5]?{{32{res_sll[31]}},res_sll[31:0]}:res_sll;
            `ysyx_050369_alu_less   :res = ALUctr[5]?{63'b0,CF}:{63'b0,SF^OF};
            `ysyx_050369_alu_setB   :res = op2;
            `ysyx_050369_alu_srl    :res = ALUctr[5]?(ALUctr[4]?{{32{res_sraw[31]}},res_sraw[31:0]}:{{32{res_srlw[31]}},res_srlw}):(ALUctr[4]?res_sra[63:0]:res_srl);
            `ysyx_050369_alu_and    :res = ALUctr[5]?(op1 & ~op2):res_and;
            `ysyx_050369_alu_or     :res = res_or;
            `ysyx_050369_alu_xor    :res = res_xor;
            `ysyx_050369_alu_mul    :res = result_lo;
            `ysyx_050369_alu_mulh   :res = result_hi;
            `ysyx_050369_alu_mulhu  :res = result_hi;
            `ysyx_050369_alu_mulhsu :res = result_hi;
            `ysyx_050369_alu_div    :res = quotient;
            `ysyx_050369_alu_rem    :res = remainder; 
            default: res = 64'b0;
        endcase
    end

// MuxKeyWithDefault #(14, 4, 64) res_choose (res, ALUctr[3:0], 64'b0, {
//     `ysyx_050369_alu_add   ,ALUctr[5]?{{32{add_res[31]}},add_res[31:0]}:add_res,
//     `ysyx_050369_alu_sll   ,ALUctr[5]?{{32{res_sll[31]}},res_sll[31:0]}:res_sll,
//     `ysyx_050369_alu_less  ,ALUctr[5]?{63'b0,CF}:{63'b0,SF^OF},
//     `ysyx_050369_alu_setB  ,op2,
//     `ysyx_050369_alu_srl   ,ALUctr[5]?(ALUctr[4]?{{32{res_sraw[31]}},res_sraw[31:0]}:{{32{res_srlw[31]}},res_srlw}):(ALUctr[4]?res_sra[63:0]:res_srl),
//     `ysyx_050369_alu_and   ,ALUctr[5]?(op1 & ~op2):res_and,
//     `ysyx_050369_alu_or    ,res_or,
//     `ysyx_050369_alu_xor   ,res_xor,
//     `ysyx_050369_alu_mul   ,result_lo,
//     `ysyx_050369_alu_mulh  ,result_hi,
//     `ysyx_050369_alu_mulhu ,result_hi,
//     `ysyx_050369_alu_mulhsu,result_hi,
//     `ysyx_050369_alu_div   ,quotient,
//     `ysyx_050369_alu_rem   ,remainder
// });
endmodule
